package com.xdog.web3.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import com.xdog.common.core.domain.R;
import com.xdog.web3.domain.price.PriceRequest;
import com.xdog.web3.exception.Web3ApiException;
import com.xdog.web3.service.IWeb3MarketService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Web3实时行情WebSocket控制器
 */
@Tag(name = "Web3实时行情", description = "Web3实时行情WebSocket推送")
@ServerEndpoint("/web3/market/ws")
@Component
@Slf4j
public class Web3WebSocketController {

    // 使用线程安全的Set存储所有连接的会话
    private static final Set<Session> sessions = new CopyOnWriteArraySet<>();

    // 注入市场服务（需要使用静态方法注入）
    private static IWeb3MarketService web3MarketService;

    @Resource
    public void setWeb3MarketService(IWeb3MarketService web3MarketService) {
        Web3WebSocketController.web3MarketService = web3MarketService;
    }

    /**
     * 连接建立时触发
     */
    @OnOpen
    @SaIgnore
    public void onOpen(Session session) {
        sessions.add(session);
        log.info("新的WebSocket连接建立，当前连接数: {}", sessions.size());

        // 发送连接成功的消息
        sendMessage(session, R.ok("WebSocket连接成功"));
    }

    /**
     * 收到客户端消息时触发
     */
    @OnMessage
    @SaIgnore
    public void onMessage(String message, Session session) {
        log.info("收到客户端消息: {}", message);
        // 可以根据客户端发送的消息来定制推送内容
        sendMessage(session, R.ok("消息已收到: " + message));
    }

    /**
     * 连接关闭时触发
     */
    @OnClose
    @SaIgnore
    public void onClose(Session session) {
        sessions.remove(session);
        log.info("WebSocket连接关闭，当前连接数: {}", sessions.size());
    }

    /**
     * 发生错误时触发
     */
    @OnError
    @SaIgnore
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误", error);
        sessions.remove(session);
    }

    /**
     * 定时推送市场数据（每5秒推送一次）
     */
    @Scheduled(fixedRate = 5000)
    @SaIgnore
    public void pushMarketData() {
        if (sessions.isEmpty()) {
            return;
        }

        try {
            // 构造请求参数
            PriceRequest priceRequest = new PriceRequest();
            priceRequest.setChainIndex("196");
            priceRequest.setTokenContractAddress("0x0cc24c51bf89c00c5affbfcf5e856c25ecbdb48e");

            // 获取市场数据
            JSONObject marketData = web3MarketService.getPrice(Collections.singletonList(priceRequest));

            // 向所有连接的客户端推送数据
            for (Session session : sessions) {
                if (session.isOpen()) {
                    sendMessage(session, R.ok(marketData));
                }
            }
        } catch (Web3ApiException e) {
            log.error("获取市场数据失败: {}", e.getMessage());
            // 向所有连接的客户端推送错误信息
            for (Session session : sessions) {
                if (session.isOpen()) {
                    sendMessage(session, R.fail(e.getHttpStatus(), "API错误: " + e.getMessage()));
                }
            }
        } catch (Exception e) {
            log.error("推送市场数据失败", e);
            // 向所有连接的客户端推送错误信息
            for (Session session : sessions) {
                if (session.isOpen()) {
                    sendMessage(session, R.fail("推送数据失败: " + e.getMessage()));
                }
            }
        }
    }

    /**
     * 发送消息到指定会话
     */
    private void sendMessage(Session session, R<?> message) {
        try {
            if (session.isOpen()) {
                session.getBasicRemote().sendText(JSONObject.toJSONString(message));
            }
        } catch (Exception e) {
            log.error("发送消息失败", e);
        }
    }
}
